home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2001 May / may_2001.iso / intercd / root / Multimedia / ^DivX_Article / virtualdub / VirtualDub-source-1_4d / f_deinterlace.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-20  |  9.8 KB  |  446 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Copyright (C) 1998-2001 Avery Lee
  3. //
  4. //    This program is free software; you can redistribute it and/or modify
  5. //    it under the terms of the GNU General Public License as published by
  6. //    the Free Software Foundation; either version 2 of the License, or
  7. //    (at your option) any later version.
  8. //
  9. //    This program is distributed in the hope that it will be useful,
  10. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. //    GNU General Public License for more details.
  13. //
  14. //    You should have received a copy of the GNU General Public License
  15. //    along with this program; if not, write to the Free Software
  16. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17.  
  18. #include <windows.h>
  19. #include <commctrl.h>
  20. #include <crtdbg.h>
  21. #include <stdio.h>
  22.  
  23. #include "resource.h"
  24. #include "filter.h"
  25. #include "gui.h"
  26. #include "cpuaccel.h"
  27.  
  28. #include "ScriptInterpreter.h"
  29. #include "ScriptValue.h"
  30. #include "ScriptError.h"
  31.  
  32. extern HINSTANCE g_hInst;
  33.  
  34. ///////////////////////////////////////////////////////////////////////////
  35.  
  36. enum {
  37.     MODE_BLEND        = 0,
  38.     MODE_DUP1        = 1,
  39.     MODE_DUP2        = 2,
  40.     MODE_DISCARD1    = 3,
  41.     MODE_DISCARD2    = 4,
  42.     MODE_UNFOLD        = 5,
  43.     MODE_FOLD        = 6
  44. };
  45.  
  46. typedef struct MyFilterData {
  47.     int mode;
  48. } MyFilterData;
  49.  
  50. static const char *g_szModes[]={
  51.     "blend",
  52.     "dup 1",
  53.     "dup 2",
  54.     "discard 1",
  55.     "discard 2",
  56.     "unfold",
  57.     "fold"
  58. };
  59.  
  60. ///////////////////////////////////////////////////////////////////////////
  61.  
  62. static void __declspec(naked) asm_blend_row_clipped(Pixel *dst, Pixel *src, PixDim w, PixOffset srcpitch) {
  63.     __asm {
  64.         push    ebp
  65.         push    edi
  66.         push    esi
  67.         push    ebx
  68.  
  69.         mov        edi,[esp+20]
  70.         mov        esi,[esp+24]
  71.         sub        edi,esi
  72.         mov        ebp,[esp+28]
  73.         mov        edx,[esp+32]
  74.  
  75. xloop:
  76.         mov        ecx,[esi]
  77.         mov        eax,0fefefefeh
  78.  
  79.         mov        ebx,[esi+edx]
  80.         and        eax,ecx
  81.  
  82.         shr        eax,1
  83.         and        ebx,0fefefefeh
  84.  
  85.         shr        ebx,1
  86.         add        esi,4
  87.  
  88.         add        eax,ebx
  89.         dec        ebp
  90.  
  91.         mov        [edi+esi-4],eax
  92.         jnz        xloop
  93.  
  94.         pop        ebx
  95.         pop        esi
  96.         pop        edi
  97.         pop        ebp
  98.         ret
  99.     };
  100. }
  101.  
  102. static void __declspec(naked) asm_blend_row(Pixel *dst, Pixel *src, PixDim w, PixOffset srcpitch) {
  103.     __asm {
  104.         push    ebp
  105.         push    edi
  106.         push    esi
  107.         push    ebx
  108.  
  109.         mov        edi,[esp+20]
  110.         mov        esi,[esp+24]
  111.         sub        edi,esi
  112.         mov        ebp,[esp+28]
  113.         mov        edx,[esp+32]
  114.  
  115. xloop:
  116.         mov        ecx,[esi]
  117.         mov        eax,0fcfcfcfch
  118.  
  119.         mov        ebx,[esi+edx]
  120.         and        eax,ecx
  121.  
  122.         shr        ebx,1
  123.         mov        ecx,[esi+edx*2]
  124.  
  125.         shr        ecx,2
  126.         and        ebx,07f7f7f7fh
  127.  
  128.         shr        eax,2
  129.         and        ecx,03f3f3f3fh
  130.  
  131.         add        eax,ebx
  132.         add        esi,4
  133.  
  134.         add        eax,ecx
  135.         dec        ebp
  136.  
  137.         mov        [edi+esi-4],eax
  138.         jnz        xloop
  139.  
  140.         pop        ebx
  141.         pop        esi
  142.         pop        edi
  143.         pop        ebp
  144.         ret
  145.     };
  146. }
  147.  
  148. static void __declspec(naked) asm_blend_row_MMX(Pixel *dst, Pixel *src, PixDim w, PixOffset srcpitch) {
  149.     static const __int64 mask0 = 0xfcfcfcfcfcfcfcfci64;
  150.     static const __int64 mask1 = 0x7f7f7f7f7f7f7f7fi64;
  151.     static const __int64 mask2 = 0x3f3f3f3f3f3f3f3fi64;
  152.     __asm {
  153.         push    ebp
  154.         push    edi
  155.         push    esi
  156.         push    ebx
  157.  
  158.         mov        edi,[esp+20]
  159.         mov        esi,[esp+24]
  160.         sub        edi,esi
  161.         mov        ebp,[esp+28]
  162.         mov        edx,[esp+32]
  163.  
  164.         movq    mm5,mask0
  165.         movq    mm6,mask1
  166.         movq    mm7,mask2
  167.         shr        ebp,1
  168.         jz        oddpart
  169.  
  170. xloop:
  171.         movq    mm2,[esi]
  172.         movq    mm0,mm5
  173.  
  174.         movq    mm1,[esi+edx]
  175.         pand    mm0,mm2
  176.  
  177.         psrlq    mm1,1
  178.         movq    mm2,[esi+edx*2]
  179.  
  180.         psrlq    mm2,2
  181.         pand    mm1,mm6
  182.  
  183.         psrlq    mm0,2
  184.         pand    mm2,mm7
  185.  
  186.         paddb    mm0,mm1
  187.         add        esi,8
  188.  
  189.         paddb    mm0,mm2
  190.         dec        ebp
  191.  
  192.         movq    [edi+esi-8],mm0
  193.         jne        xloop
  194.  
  195. oddpart:
  196.         test    byte ptr [esp+28],1
  197.         jz        nooddpart
  198.  
  199.         mov        ecx,[esi]
  200.         mov        eax,0fcfcfcfch
  201.         mov        ebx,[esi+edx]
  202.         and        eax,ecx
  203.         shr        ebx,1
  204.         mov        ecx,[esi+edx*2]
  205.         shr        ecx,2
  206.         and        ebx,07f7f7f7fh
  207.         shr        eax,2
  208.         and        ecx,03f3f3f3fh
  209.         add        eax,ebx
  210.         add        eax,ecx
  211.         mov        [edi+esi],eax
  212.  
  213. nooddpart:
  214.  
  215.         pop        ebx
  216.         pop        esi
  217.         pop        edi
  218.         pop        ebp
  219.         ret
  220.     };
  221. }
  222.  
  223. static int deinterlace_run(const FilterActivation *fa, const FilterFunctions *ff) {
  224.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  225.     Pixel32 *src = fa->src.data;
  226.     Pixel32 *dst = fa->dst.data;
  227.     PixDim w = fa->src.w;
  228.     PixDim h = fa->src.h;
  229.     void (*blend_func)(Pixel32 *, Pixel32 *, PixDim, PixOffset);
  230.  
  231.     switch(mfd->mode) {
  232.     case MODE_BLEND:
  233.         if (h<2) return 0;
  234.  
  235.         blend_func = MMX_enabled ? asm_blend_row_MMX : asm_blend_row;
  236.  
  237.         asm_blend_row_clipped(dst, src, fa->src.w, fa->src.pitch);
  238.         if (h-=2)
  239.             do {
  240.                 dst = (Pixel *)((char *)dst + fa->dst.pitch);
  241.  
  242.                 blend_func(dst, src, fa->src.w, fa->src.pitch);
  243.  
  244.                 src = (Pixel *)((char *)src + fa->src.pitch);
  245.             } while(--h);
  246.  
  247.         asm_blend_row_clipped((Pixel *)((char *)dst + fa->dst.pitch), src, fa->src.w, fa->src.pitch);
  248.  
  249.         if (MMX_enabled)
  250.             __asm emms
  251.         break;
  252.     case MODE_DUP2:
  253.         src = (Pixel *)((char *)src + fa->src.pitch);
  254.         dst = (Pixel *)((char *)src - fa->dst.pitch);
  255.     case MODE_DUP1:
  256.         dst = (Pixel *)((char *)src + fa->dst.pitch);
  257.  
  258.         if (h>>=1)
  259.             do {
  260.                 memcpy(dst, src, fa->src.w*4);
  261.  
  262.                 src = (Pixel *)((char *)src + fa->src.pitch*2);
  263.                 dst = (Pixel *)((char *)dst + fa->dst.pitch*2);
  264.             } while(--h);
  265.         break;
  266.  
  267.     case MODE_UNFOLD:
  268.         {
  269.             VBitmap vbmsrc;
  270.  
  271.             vbmsrc = fa->src;
  272.             vbmsrc.modulo += vbmsrc.pitch;
  273.             vbmsrc.pitch<<=1;
  274.             vbmsrc.h >>= 1;
  275.  
  276.             fa->dst.BitBlt(0, 0, &vbmsrc, 0, 0, -1, -1);
  277.  
  278.             vbmsrc.data = (Pixel32 *)((char *)vbmsrc.data + fa->src.pitch);
  279.  
  280.             fa->dst.BitBlt(fa->src.w, 0, &vbmsrc, 0, 0, -1, -1);
  281.         }
  282.         break;
  283.  
  284.     case MODE_FOLD:
  285.         {
  286.             VBitmap vbmdst;
  287.  
  288.             vbmdst = fa->dst;
  289.             vbmdst.modulo += vbmdst.pitch;
  290.             vbmdst.pitch<<=1;
  291.             vbmdst.h >>= 1;
  292.  
  293.             vbmdst.BitBlt(0, 0, &fa->src, 0, 0, -1, -1);
  294.  
  295.             vbmdst.data = (Pixel32 *)((char *)vbmdst.data + fa->dst.pitch);
  296.  
  297.             vbmdst.BitBlt(0, 0, &fa->src, fa->dst.w, 0, -1, -1);
  298.         }
  299.         break;
  300.     }
  301.  
  302.     return 0;
  303. }
  304.  
  305. static long deinterlace_param(FilterActivation *fa, const FilterFunctions *ff) {
  306.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  307.  
  308.     switch(mfd->mode) {
  309.     case MODE_BLEND:
  310.         return FILTERPARAM_SWAP_BUFFERS;
  311.  
  312.     case MODE_DUP1:
  313.     case MODE_DUP2:
  314.         break;
  315.  
  316.     case MODE_DISCARD1:
  317.         fa->dst.offset    = fa->src.offset + fa->dst.pitch;
  318.     case MODE_DISCARD2:
  319.         fa->dst.h        >>= 1;
  320.         fa->dst.pitch    <<= 1;
  321.         fa->dst.modulo    = fa->dst.Modulo();
  322.         break;
  323.  
  324.     case MODE_UNFOLD:
  325.         fa->dst.h        >>= 1;
  326.         fa->dst.w        <<=1;
  327.         fa->dst.AlignTo8();
  328.         return FILTERPARAM_SWAP_BUFFERS;
  329.  
  330.     case MODE_FOLD:
  331.         fa->dst.h        <<= 1;
  332.         fa->dst.w        >>= 1;
  333.         fa->dst.AlignTo8();
  334.         return FILTERPARAM_SWAP_BUFFERS;
  335.     }
  336.  
  337.     return 0;
  338. }
  339.  
  340. static BOOL APIENTRY DeinterlaceDlgProc(HWND hDlg, UINT message, UINT wParam, LONG lParam) {
  341.     MyFilterData *mfd;
  342.  
  343.     switch (message)
  344.     {
  345.         case WM_INITDIALOG:
  346.             {
  347.                 mfd = (MyFilterData *)lParam;
  348.                 SetWindowLong(hDlg, DWL_USER, (LONG)mfd);
  349.  
  350.                 switch(mfd->mode) {
  351.                 case MODE_BLEND:        CheckDlgButton(hDlg, IDC_MODE_BLEND, BST_CHECKED); break;
  352.                 case MODE_DUP1:            CheckDlgButton(hDlg, IDC_MODE_DUP1, BST_CHECKED); break;
  353.                 case MODE_DUP2:            CheckDlgButton(hDlg, IDC_MODE_DUP2, BST_CHECKED); break;
  354.                 case MODE_DISCARD1:        CheckDlgButton(hDlg, IDC_MODE_DISCARD1, BST_CHECKED); break;
  355.                 case MODE_DISCARD2:        CheckDlgButton(hDlg, IDC_MODE_DISCARD2, BST_CHECKED); break;
  356.                 case MODE_UNFOLD:        CheckDlgButton(hDlg, IDC_MODE_UNFOLD, BST_CHECKED); break;
  357.                 case MODE_FOLD:            CheckDlgButton(hDlg, IDC_MODE_FOLD, BST_CHECKED); break;
  358.                 }
  359.             }
  360.  
  361.             return (TRUE);
  362.  
  363.         case WM_COMMAND:
  364.             switch(LOWORD(wParam)) {
  365.             case IDOK:
  366.                 {
  367.                     mfd = (MyFilterData *)GetWindowLong(hDlg, DWL_USER);
  368.                     
  369.                     if (IsDlgButtonChecked(hDlg, IDC_MODE_BLEND))        mfd->mode = MODE_BLEND;
  370.                     if (IsDlgButtonChecked(hDlg, IDC_MODE_DUP1))        mfd->mode = MODE_DUP1;
  371.                     if (IsDlgButtonChecked(hDlg, IDC_MODE_DUP2))        mfd->mode = MODE_DUP2;
  372.                     if (IsDlgButtonChecked(hDlg, IDC_MODE_DISCARD1))    mfd->mode = MODE_DISCARD1;
  373.                     if (IsDlgButtonChecked(hDlg, IDC_MODE_DISCARD2))    mfd->mode = MODE_DISCARD2;
  374.                     if (IsDlgButtonChecked(hDlg, IDC_MODE_UNFOLD))        mfd->mode = MODE_UNFOLD;
  375.                     if (IsDlgButtonChecked(hDlg, IDC_MODE_FOLD))        mfd->mode = MODE_FOLD;
  376.  
  377.                     EndDialog(hDlg, 0);
  378.                 }
  379.                 return TRUE;
  380.             case IDCANCEL:
  381.                 EndDialog(hDlg, 1);
  382.                 return TRUE;
  383.  
  384.             }
  385.             break;
  386.  
  387.     }
  388.     return FALSE;
  389. }
  390.  
  391. static int deinterlace_config(FilterActivation *fa, const FilterFunctions *ff, HWND hWnd) {
  392.     return DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_FILTER_DEINTERLACE), hWnd, DeinterlaceDlgProc, (LONG)fa->filter_data);
  393. }
  394.  
  395. static void deinterlace_string(const FilterActivation *fa, const FilterFunctions *ff, char *buf) {
  396.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  397.  
  398.     wsprintf(buf, " (mode: %s)", g_szModes[mfd->mode]);
  399. }
  400.  
  401. static void deinterlace_script_config(IScriptInterpreter *isi, void *lpVoid, CScriptValue *argv, int argc) {
  402.     FilterActivation *fa = (FilterActivation *)lpVoid;
  403.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  404.  
  405.     mfd->mode    = argv[0].asInt();
  406.  
  407.     if (mfd->mode < 0 || mfd->mode > 6)
  408.         mfd->mode = 0;
  409. }
  410.  
  411. static ScriptFunctionDef deinterlace_func_defs[]={
  412.     { (ScriptFunctionPtr)deinterlace_script_config, "Config", "0i" },
  413.     { NULL },
  414. };
  415.  
  416. static CScriptObject deinterlace_obj={
  417.     NULL, deinterlace_func_defs
  418. };
  419.  
  420. static bool deinterlace_script_line(FilterActivation *fa, const FilterFunctions *ff, char *buf, int buflen) {
  421.     MyFilterData *mfd = (MyFilterData *)fa->filter_data;
  422.  
  423.     _snprintf(buf, buflen, "Config(%d)", mfd->mode);
  424.  
  425.     return true;
  426. }
  427.  
  428. FilterDefinition filterDef_deinterlace={
  429.     0,0,NULL,
  430.     "deinterlace",
  431.     "Removes scanline artifacts from interlaced video.\r\n\r\n[Assembly optimized][MMX optimized]",
  432.     NULL,NULL,
  433.     sizeof(MyFilterData),
  434.     NULL,NULL,
  435.     deinterlace_run,
  436.     deinterlace_param,
  437.     deinterlace_config,
  438.     deinterlace_string,
  439.     NULL,
  440.     NULL,
  441.  
  442.     &deinterlace_obj,
  443.     deinterlace_script_line,
  444. };
  445.  
  446.